package com.link_with_health.controller;

import com.alibaba.fastjson.JSONObject;
import com.link_with_health.common.Page;
import com.link_with_health.common.Result;
import com.link_with_health.common.TokenMap;
import com.link_with_health.exception.BaseException;
import com.link_with_health.exception.NullQueryResultException;
import com.link_with_health.model.AdminLogEntity;
import com.link_with_health.model.AdminUserEntity;
import com.link_with_health.model.BatchModel;
import com.link_with_health.model.DepartmentsEntity;
import com.link_with_health.model.DoctorEntity;
import com.link_with_health.model.UserEntity;
import com.link_with_health.model.WaitingQueueEntity;
import com.link_with_health.service.AdminLogService;
import com.link_with_health.service.BatchOperationService;
import com.link_with_health.service.DepartmentsService;
import com.link_with_health.service.DoctorService;
import com.link_with_health.service.UserService;
import com.link_with_health.service.WaitingQueueService;
import com.link_with_health.utils.JsonUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

@Controller
@RequestMapping("/api/doctor")
public class DoctorController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private final String AUTH_TOKEN = "Authorization";
    private TokenMap tokenMap = TokenMap.getInstance();

    //医生可被用户搜索到的状态
    private final Integer[] DOCTOR_BEEN_SEEN_BY_USER = new Integer[]{1,4,5};

    //医生可被系统管理员所搜索到的状态
    private final Integer[] DOCTOR_BEEN_SEEN_BY_ADMIN = new Integer[]{1,2,3,4,5,6,7};

    //操作者类型
    // 0----问诊系统用户
    // 1----后台管理员
    int operatorType = 0;

    @Resource(name = "doctorService")
    DoctorService doctorService;

    @Resource(name = "departmentsService")
    DepartmentsService departmentsService;

    @Resource(name = "adminLogService")
    AdminLogService adminLogService;

    @Resource(name = "userService")
    UserService userService;

    @Resource (name = "waitingQueueService" )
    WaitingQueueService waitingQueueService;

    @Resource(name = "batchOperationService")
    BatchOperationService batchOperationService;

    /**
     * 获取医生用户信息
     * @param json 数据
     * @param request 请求
     * @return
     */
    @RequestMapping("/findDoctorInfo")
    @ResponseBody
    public Result findDoctorInfo(@RequestBody Map<String,Object> json
            , HttpServletRequest request){
        String token = request.getHeader(AUTH_TOKEN);
        String msg = "请求失败";

        if(tokenMap.containsKey(token)
                && tokenMap.get(token) instanceof AdminLogEntity){
            operatorType = 1;
        }

        String method = (String) json.get("method");
        try {
            HashMap<String,Object> params =
                    (HashMap<String,Object>)json.get("params");

            return method(method,params);

        } catch (Exception e) {
            logger.error("[req error by find doctor]",e);
            msg = "获取失败";
            if(e instanceof NullQueryResultException){
                return Result.notResult("无查找结果",null);
            }

        }
        return Result.fail(msg,null);
    }

    /**
     * 获取医生用户信息
     * @param json 数据 ids 医生id数组
     * @param request 请求
     * @return
     */
    @RequestMapping("/deleteDoctorInfo")
    @ResponseBody
    public Result deleteDoctorInfo(@RequestBody JSONObject json
            , HttpServletRequest request){
        String token = request.getHeader(AUTH_TOKEN);
        String msg = "验签验证失败";

        if(token==null|| !tokenMap.containsKey(token)){
            logger.error("[delete sysInfo info failed]");
            return Result.fail(msg);
        }

        Integer adminId = Math.toIntExact(tokenMap.get(token)
                instanceof AdminUserEntity
                ? ((AdminUserEntity) tokenMap.get(token)).getAdminID()
                : ((UserEntity) tokenMap.get(token)).getUserId());
        int errorNumber = 0;
        try{
            Long[] ids = json.getObject("ids",Long[].class);
            //备份
            StringBuilder oldEntity = new StringBuilder();

            for(Long idBk: ids){
                DoctorEntity entity = doctorService.getDoctorsByDrId(idBk);
                oldEntity.append("\n").append(JsonUtil.obj2json(entity));
            }

            List<BatchModel> models = new ArrayList<>(ids.length);
            int index = 0;
            // user_id=>100000为不能使用的用户id  doctor_status =>8  删除状态
            String sql = "t.user_id = 100000" +
                    ", t.real_name = 'null'"+
                    ", t.per_info = null, t.doctor_status = 8";

            for(;index <ids.length;index++){
                BatchModel model = new BatchModel("doctor"
                        , "","",
                        "dr_id",ids[index].toString(),sql);
                models.add(model);
            }

            batchOperationService.batchUpdateLikeDelete(models);

            //记录操作
            AdminLogEntity log = new AdminLogEntity(0L, adminId,
                    "删除", "doctor", oldEntity.toString());
            adminLogService.addAdminLog(log);

            return Result.success("成功操作");

        }catch(Exception e){
            logger.error("delete doctor failed",e);
            msg = "删除失败";
        }

        return Result.fail(msg);
    }

    /**
     * 修改医生用户信息
     * @param json 数据 json
     * @param request 请求
     * @return
     */
    @RequestMapping("/modifyDoctorInfo")
    @ResponseBody
    public Result modifyDoctorInfo(@RequestBody JSONObject json
            , HttpServletRequest request){
        String token = request.getHeader(AUTH_TOKEN);
        String msg = "验签验证失败";

        if(token==null|| !tokenMap.containsKey(token)){
            logger.error("[get patient info failed]");
            return Result.fail(msg);
        }
        Integer adminId = Math.toIntExact(tokenMap.get(token)
                instanceof AdminUserEntity
                ? ((AdminUserEntity) tokenMap.get(token)).getAdminID()
                : ((UserEntity) tokenMap.get(token)).getUserId());

        try{
            DoctorEntity entity = JsonUtil
                    .json2obj(json.toJSONString(), DoctorEntity.class);
            try{
                if(entity.getUserId() != null)
                    userService.getUserByUserId(entity.getUserId());
                else
                    entity.setUserId(100000L);
            }catch(Exception e){
                return Result.fail("无效用户id",null);
            }

            DoctorEntity oldEntity = doctorService
                    .getDoctorsByDrId(entity.getDrId());

            doctorService.changeDoctor(entity);
            entity = doctorService.getDoctorsByDrId(entity.getDrId());

            //备份
            String object = JsonUtil.obj2json(oldEntity);
            AdminLogEntity log = new AdminLogEntity(0L, adminId
                    , "修改", "doctor", object);

            adminLogService.addAdminLog(log);

            return Result.success("操作成功", entity);

        }catch(Exception e){
            logger.error("[modify doctor failed]",e);
            msg = "操作失败";
        }

        return Result.fail(msg,null);
    }

    /**
     * 添加医生用户信息
     * @param json 数据 json
     * @param request 请求
     * @return
     */
    @RequestMapping("/addDoctorInfo")
    @ResponseBody
    public Result addDoctorInfo(@RequestBody JSONObject json
            , HttpServletRequest request){
        String token = request.getHeader(AUTH_TOKEN);
        String msg = "验签验证失败";

        if(token==null|| !tokenMap.containsKey(token)){
            logger.error("[get patient info failed]");
            return Result.fail(msg);
        }
        Integer adminId = Math.toIntExact(tokenMap.get(token)
                instanceof AdminUserEntity
                ? ((AdminUserEntity) tokenMap.get(token)).getAdminID()
                : ((UserEntity) tokenMap.get(token)).getUserId());

        try{
            DoctorEntity entity = JsonUtil
                    .json2obj(json.toJSONString(), DoctorEntity.class);

            try{
                if(entity.getUserId() != null)
                    userService.getUserByUserId(entity.getUserId());
                else
                    entity.setUserId(100000L);
            }catch(Exception e){
                return Result.fail("无效用户id",null);
            }

            doctorService.addDoctor(entity);
            entity = doctorService.getDoctorsByDrId(entity.getDrId());

            //创建候诊室
            WaitingQueueEntity waitingQueue = new WaitingQueueEntity();
            waitingQueue.setDoctorId(entity.getDrId());
            waitingQueue.setPatientQueue("##");
            waitingQueue.setMaxQueue(10);
            waitingQueue.setMaxAppointment(10);
            waitingQueue.setIsOpen(false);
            waitingQueueService.addWaitingQueue(waitingQueue);
            waitingQueue = waitingQueueService
                    .getWaitingQueueById(waitingQueue.getQueueId());
            String queueObject = JsonUtil.obj2json(waitingQueue);

            //备份
            String object = JsonUtil.obj2json(entity);
            AdminLogEntity log = new AdminLogEntity(0L, adminId
                    ,"增加", "doctor", object);
            AdminLogEntity queueLog = new AdminLogEntity(0L, adminId
                    , "增加" , "waitingQueue", queueObject);


            adminLogService.addAdminLog(log);
            adminLogService.addAdminLog(queueLog);

            return Result.success("成功修改",entity);


        }catch(Exception e){
            logger.error("[add inquiry info failed]",e);
            msg = "操作失败 请检查输入的参数";
        }

        return Result.fail(msg);
    }

    /**
     * 通过id获取医生用户信息
     * @param json 数据 json doctorId
     * @param request 请求
     * @return
     */
    @RequestMapping("/selectDoctorById")
    @ResponseBody
    public Result selectDoctorById(@RequestBody JSONObject json
            , HttpServletRequest request){
        String msg = "请求失败 无授权信息";
        String token = request.getHeader(AUTH_TOKEN);
        tokenMap.containsKey(token);

        try {

            Long doctorId = json.getLong("doctorId") ;
            DoctorEntity entity = doctorService.getDoctorsByDrId(doctorId);

            return Result.success(entity);


        } catch(Exception e) {
            logger.error("[get doctor info by id failed]",e);
            msg = "获取数据失败";
        }

        return Result.fail(msg);
    }

    /**
     * 通过id获取医生用户信息
     * @param json 数据 json doctorId
     * @param request 请求
     * @return
     */
    @RequestMapping("/selectDoctorByUserId")
    @ResponseBody
    public Result selectDoctorByUserId(@RequestBody JSONObject json
            , HttpServletRequest request){
        String msg = "请求失败 无授权信息";
        String token = request.getHeader(AUTH_TOKEN);
        tokenMap.containsKey(token);

        try {

            Long userId = json.getLong("userId") ;
            DoctorEntity entity = doctorService.getDoctorsByUserId(userId);

            return Result.success(entity);


        } catch(Exception e) {
            logger.error("[get doctor info by id failed]",e);
            msg = "获取数据失败";
        }

        return Result.fail(msg);
    }


    /**
     * 通过授权信息获取医生信息
     * @param request 请求
     * @return 医生信息
     */
    @GetMapping("/accessDoctorInfo")
    @ResponseBody
    public Result accessDoctorInfo(HttpServletRequest request){
        String msg ="请求失败 无授权信息";
        String token = request.getHeader(AUTH_TOKEN);
        try {
            UserEntity entity = (UserEntity) tokenMap.get(token);
            DoctorEntity doctor = doctorService
                    .getDoctorsByUserId(entity.getUserId());

            return Result.success(doctor);

        } catch(Exception e){
            logger.error("",e);
            msg = "获取信息失败";
        }

        return Result.fail(msg);
    }


    /**
     * 设置医生用户状态信息
     * @param json 数据
     * @param request 请求
     * @return
     */
    @RequestMapping("/statusSetting")
    @ResponseBody
    public Result statusSetting(@RequestBody JSONObject json
            , HttpServletRequest request){
        String msg = "请求失败 无授权信息";
        String token = request.getHeader(AUTH_TOKEN);
        tokenMap.containsKey(token);

        try {
            Long doctorId = json.getLong("doctorId");
            Integer doctorStatus = json.getInteger("doctorStatus");
            DoctorEntity entity = doctorService.getDoctorsByDrId(doctorId);

            entity.setDoctorStatus(doctorStatus);
            doctorService.changeDoctor(entity);

            entity = doctorService.getDoctorsByDrId(entity.getDrId());

            return Result.success(entity);

        } catch(Exception e) {
            logger.error("[change status failed]",e);
            msg = "修改状态失败";
        }

        return Result.fail(msg);
    }

    /**
     * 获取职称信息
     * @param request 请求
     * @return 数据
     */
    @RequestMapping("/getTitleInfo")
    @ResponseBody
    public Result getTitleInfo(HttpServletRequest request){
        String msg = "请求失败 无授权信息";
        String token = request.getHeader(AUTH_TOKEN);
        if(!tokenMap.containsKey(token)){
            logger.error("[not token]");
            return Result.fail(msg);
        }

        try{
            return Result.success(doctorService.getAllTitle());

        }catch(Exception e){
            logger.error("[get title failed]",e);
            msg = "获取职称失败";
        }

        return Result.fail(msg);
    }

    /**
     * 获取职称信息
     * @param request 请求
     * @return 数据
     */
    @RequestMapping("/getStatusInfo")
    @ResponseBody
    public Result getStatusInfo(HttpServletRequest request){
        String msg = "请求失败 无授权信息";
        String token = request.getHeader(AUTH_TOKEN);
        if(!tokenMap.containsKey(token)){
            logger.error("[not token]");
            return Result.fail(msg);
        }

        try{
            return Result.success(doctorService.getAllStatus());

        }catch(Exception e){
            logger.error("[get title failed]",e);
            msg = "获取状态失败";
        }

        return Result.fail(msg);
    }


    /**
     * 根据method选择筛选不同数据的方法
     * @param method 方法
     * @param params 筛选参数
     * @return 封装好的数据
     * @throws Exception 异常
     */
    private Result method(String method, HashMap<String,Object> params)
            throws Exception{
        List<DoctorEntity> list = new ArrayList<DoctorEntity>();
        String msg = "数据获取失败";

        switch(method){
            case "all": case "all-page":{
                 list = doctorService
                        .getAllDoctors();

            }
                break;
            case "departmentName":{
                String departmentName = (String) params
                        .get("departmentName");
                DepartmentsEntity entity = departmentsService
                        .getDepartByNameExact(departmentName);

                list = doctorService
                        .getDoctorsByDepartment(entity.getDepartmentId());

            }
                break;
            case "doctorOrHospital": case "name-page":{
                String name = (String) params.get("name");
                list = doctorService
                        .searchDoctorsByNameOrHospitalName(name,name);
            }
                break;
            case "id-page":{
                String id = (String) params.get("id");
                try {
                    list.add(doctorService.getDoctorsByDrId(Long.valueOf(id)));
                }catch (Exception e){
                    logger.warn("[not result by search doctorId]");
                }
                try{
                    list.add(doctorService.getDoctorsByUserId(Long.valueOf(id)));
                }catch(Exception e){
                    logger.warn("[not result by search userBind]");
                }
            }
                break;

            default:
                logger.error("unknown method=>" + method);
                return Result.fail("未知查找方法");
        }
        if(list == null || list.isEmpty())
            throw new NullQueryResultException("[not result fo doctor]");

        //过滤数据
        list = list.stream().distinct().filter(DoctorEntity ->
                isVisible(DoctorEntity.getDoctorStatus(),operatorType))
                .collect(Collectors.toList());

        //封装 带页数数据
        if(method.contains("page")){
            Integer current = Integer.valueOf(String.valueOf(params.get("current"))) ;
            Integer size = Integer.valueOf(String.valueOf(params.get("size")));
            Page<DoctorEntity> page = new Page<>(list, size, current);
            return Result.success(page.getPageDate());
        }

        return Result.success(list);

    }

    private boolean isVisible(int status,int operatorType){
         if(0 == operatorType)
            for(int num : DOCTOR_BEEN_SEEN_BY_USER)
                if(num == status)
                    return true;

         if(1 == operatorType)
             for (int num1 : DOCTOR_BEEN_SEEN_BY_ADMIN)
                 if(num1 == status)
                     return true;

        return false;
    }

}
